<template>
  <div>
    <!-- 例一 :全局自定义指定 -->
    <div class="example">
      <input
        type="text"
        class="border-primary"
        v-focus
        placeholder="自定义指令聚焦输入框"
      />
      <span>v-focus</span>
    </div>

    <div class="example">
      <button v-throttle:[this]="[2000, 5]" @click="testVthrottle">
        v-throttle
      </button>
    </div>

    <!-- 例二：局部自定义指定 -->
    <div class="example">
      <button @click="show = !show" class="mr-1">销毁{{ number }}</button>
      <button v-if="show" v-append-text="`hello ${number}`" @click="number++">
        点按钮</button
      >v-append-text="`hello ${number}
    </div>

    <hr />

    <div class="smallexample">
      <p class="point mt-1">知识点：</p>
      <a
        href="https://cn.vuejs.org/v2/guide/custom-directive.html"
        target="__blank"
        >自定义指令</a
      >
      <pre class="border border-primary">
指令定义对象可以提供如下几个钩子函数 (均为可选):
- bind：只调用一次，指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
- inserted：被绑定元素插入父节点时调用 (仅保证父节点存在，但不一定已被插入文档中)
- update：所在组件的 VNode 更新时调用，但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变，也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
- componentUpdated：指令所在组件的 VNode 及其子 VNode 全部更新后调用
- unbind：只调用一次，指令与元素解绑时调用。

钩子函数参数
指令钩子函数会被传入以下参数：

-el：指令所绑定的元素，可以用来直接操作 DOM。
-binding：一个对象，包含以下 property：
       name：指令名，不包括 v- 前缀。
       value：指令的绑定值，例如：v-my-directive="1 + 1" 中，绑定值为 2。
       oldValue：指令绑定的前一个值，仅在 update和componentUpdated 钩子中可用。无论值是否改变都可用。
       expression：字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中，表达式为 "1 + 1"。
       arg：传给指令的参数，可选。例如 v-my-directive:foo   中，参数为 "foo"。
       modifiers：一个包含修饰符的对象。例如：v-my-directive.foo.bar 中，修饰符对象为 { foo: true, bar: true }。
-vnode：Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
-oldVnode：上一个虚拟节点，仅在 update 和 componentUpdated 钩子中可用。
      </pre>
    </div>
  </div>
</template>
<script>
export default {
  name: 'customerDirective',
  directives: {
    appendText: {
      bind() {
        console.log('bind')
      },
      inserted(el, binding) {
        const thieEleParentEle = el.parentElement
        const textNode = document.createTextNode(
          'binding.value: ' + binding.value
        )
        // ELE API:appendChild()如果文档树中已经存在了 newchild，它将从文档树中删除，然后重新插入它的新位置。
        el.appendChild(textNode)
        //  if(thieEleParentEle)
        let preEle = null
        if (thieEleParentEle.getElementsByTagName('pre').length < 1) {
          preEle = document.createElement('pre')
          preEle.append('binding: ' + JSON.stringify(binding, null, 4))
          thieEleParentEle.append(preEle)

          console.log('inserted', el, binding)
        }
      },
      update() {
        console.log('update')
      },
      // 指令所在组件的 VNode 及其子 VNode 全部更新后调用
      componentUpdated(el, binding) {
        console.log(el.parentElement.childNodes)
        // 移除本DOM的最后一个节点
        el.removeChild(el.childNodes[el.childNodes.length - 1])
        console.log(binding.oldValue, binding.value)
        if (binding.oldValue !== binding.value) {
          el.appendChild(
            document.createTextNode('binding.value: ' + binding.value)
          )
        }
        console.log('componentUpdated')
      },
      unbind() {
        console.log('unbind')
      }
    }
  },
  data() {
    return { number: 1, show: true }
  },
  methods: {
    testVthrottle() {
      console.log('111')
    }
  },
  activated: {},
  deactivated: {}
}
</script>
<style lang="less" scoped></style>
